
# =============== 接口请求 ===============

# =============== 接口 ok 请求 ===============

from sre_constants import CATEGORY_NOT_SPACE
import okex.Account_api as Account
import okex.Funding_api as Funding
import okex.Market_api as Market
import okex.Public_api as Public
import okex.Trade_api as Trade
import okex.subAccount_api as SubAccount
import okex.status_api as Status

import math
import time
import cy_log
import cy_config
import cy_operate

user_accountAPI = Account.AccountAPI(cy_config.user_api_key, cy_config.user_secret_key, cy_config.user_passphrase, False, cy_config.flag)
user_tradeAPI = Trade.TradeAPI(cy_config.user_api_key, cy_config.user_secret_key, cy_config.user_passphrase, False, cy_config.flag)
user_publicAPI = Public.PublicAPI(cy_config.user_api_key, cy_config.user_secret_key, cy_config.user_passphrase, False, cy_config.flag)
user_fundingAPI = Funding.FundingAPI(cy_config.user_api_key, cy_config.user_secret_key, cy_config.user_passphrase, False, cy_config.flag)
marketAPI = Market.MarketAPI(cy_config.user_api_key, cy_config.user_secret_key, cy_config.user_passphrase, False, cy_config.flag)

my_postion_risks = []
my_postion_orders = []

# 加载主账户持仓数据
def initMyRisk():

    global my_postion_risks

    # 主用户持仓数据获取
    my_postion_risks = getMyPositionRisk()

# 加载主账户挂单数据
def initMyOrders():
    # 主用户持仓数据获取
    global my_postion_orders

    my_postion_orders = get_my_orders()

    return my_postion_orders

# 获取主账户持仓信息
def getMyPositionRisk():

    all_chicans = []

    try:
        # 查看持仓信息  Get Positions
        result = user_accountAPI.get_positions('SWAP')
        cy_log.printAndInLog('获取持仓数据： ' + str(result))

        data = result['data']

        for item in data:
            
            time.sleep(cy_config.min_sleep_amount)

            risk_sz = item['pos']

            if float(risk_sz) != 0:

                all_chicans.append(item)

    except Exception as e:
        cy_log.printAndInLog('=========== 报错 ============')
        cy_log.printAndInLog('获取持仓数据失败： ' + str(e))
        cy_log.printAndInLog('=========== 报错 ============')
    else:
        pass

    return all_chicans

# 获取账户挂单数据 出了订单委托挂单 还有订单的策略单，这里只获取委托单
def get_my_orders():
    
    try:
        result = user_tradeAPI.get_order_list(instType='SWAP')
        result = result['data']

    except Exception as e:
        cy_log.printAndInLog('=========== 报错 ============')
        cy_log.printAndInLog('获取挂单数据失败：' + str(e))
        cy_log.printAndInLog('=========== 报错 ============')
    else:
        pass

    return result

# 调整杠杆
def changeIeverage(symbol):
    try:
        # 设置杠杆倍数  symbol 格式为： ETH-USDT-SWAP

        if 'SWAP' in symbol and '-' in symbol:
            pass
        else:
            symbol = symbol + '-SWAP'
            symbol = symbol.replace('USDT', '-USDT')

        result = user_accountAPI.set_leverage(instId=symbol, lever=str(cy_config.leverage), mgnMode='cross')
        cy_log.printAndInLog('杠杆设置结果：' + str(result))
    except Exception as e:
        cy_log.printAndInLog('=========== 报错 ============')
        cy_log.printAndInLog('设置杠杆倍数失败：' + str(e))
        cy_log.printAndInLog('=========== 报错 ============')
    else:
        pass

# 获取金额 可用保证金
def getBalance():

    result = None

    cur_total_price = 0

    try:
        result = user_accountAPI.get_account('USDT')

        data = result['data']
        price_item = data[0]
        detail_item = price_item['details'][0]
        cur_total_price = detail_item['availEq']

    except Exception as e:
        pass
    else:
        pass

    return cur_total_price

# 获取金额信息
def getBalances():

    result = None

    try:
        result = user_accountAPI.get_account('USDT')

        data = result['data']
        price_item = data[0]
        detail_item = price_item['details']

        return detail_item

    except Exception as e:
        pass
    else:
        pass

    return None

# 获取币种最新价格
def getPrice(symbol):

    # 获取指数行情  Get Index Tickers symbol 格式为 ETH-USDT
    if 'SWAP' in symbol and '-' in symbol:
            pass
    else:
        symbol = symbol + '-SWAP'
        symbol = symbol.replace('USDT', '-USDT')

    try:
        result = None

        isLoopGO = True

        while isLoopGO:

            time.sleep(cy_config.sleep_amount)
            
            try:

                result = user_publicAPI.get_mark_price('SWAP', instId=symbol)

                cy_log.printAndInLog('价格获取： ' + str(result))

                item = result['data']
                idxPx = item[0]['markPx']

                isLoopGO = False

                return idxPx

            except Exception as e:
                cy_log.printAndInLog('=========== 报错 ============')
                cy_log.printAndInLog('价格获取失败： ' + str(e))
                cy_log.printAndInLog('=========== 报错 ============')
                isLoopGO = True

    except Exception as e:
        cy_log.printAndInLog('=========== 报错 ============')
        cy_log.printAndInLog('价格获取失败： ' + str(e))
        cy_log.printAndInLog('=========== 报错 ============')
    else:
        pass

    return None

def getUserTrades(symbol, startTime, endTime):

    result = None
    
    if 'SWAP' in symbol and '-' in symbol:
            pass
    else:
        symbol = symbol + '-SWAP'
        symbol = symbol.replace('USDT', '-USDT')

    try:
        # 获取历史订单记录（近七天） Get Order History (last 7 days）
        result = user_tradeAPI.get_orders_history('SWAP', instId=symbol)

        cy_log.printAndInLog("交易记录获取：" + str(result['msg']))

        result = result['data']

    except Exception as e:
        cy_log.printAndInLog("交易记录获取失败：" + str(e))
    else:
        pass

    return result

def getUserLongTrades(startTime, endTime):
    
    result = None

    try:
        # 获取历史订单记录（近三个月）
        result = user_tradeAPI.orders_history_archive('SWAP', state='filled', begin=startTime, end=endTime)

        cy_log.printAndInLog("交易记录获取：" + str(result['msg']) + ' 订单数量：' + str(len(result['data'])))

        result = result['data']

    except Exception as e:
        cy_log.printAndInLog("交易记录获取失败：" + str(e))
    else:
        pass

    time.sleep(0.3)

    return result

# 根据id得到订单
def getOrderWithId(newClientOrderId, isMore):

    try:

        symbol = cy_config.symbol

        if 'SWAP' in symbol and '-' in symbol:
            pass
        else:
            symbol = symbol + '-SWAP'
            symbol = symbol.replace('USDT', '-USDT')

        result = None

        isLoopGO = True

        while isLoopGO:

            time.sleep(cy_config.sleep_amount)

            try:
                
                result = user_tradeAPI.get_orders(symbol, clOrdId=newClientOrderId)

                if isMore:
                    cy_log.printAndInLog_more('订单获取 ' + str(result))
                else:
                    cy_log.printAndInLog_less('订单获取 ' + str(result))

                reslut_code = result['code']

                if int(reslut_code) == 51603:

                    # 订单不存在 Order does not exist
                    # 自己构建一个订单 状态为撤销
                    my_order = {
                        'state' : 'canceled'
                    }

                    return my_order

                result = result['data'][0]

                isLoopGO = False

            except Exception as e:

                if isMore:
                    cy_log.printAndInLog_more('订单获取失败 ' + str(e))
                else:
                    cy_log.printAndInLog_less('订单获取失败 ' + str(e))

                # 重新请求
                isLoopGO = True

            else:
                isLoopGO = False
    except Exception as e:
        if isMore:
            cy_log.printAndInLog_more('=========== 报错 ============')
            cy_log.printAndInLog_more('获取订单报错：' + str(e))
            cy_log.printAndInLog_more('订单id：' + newClientOrderId)
            cy_log.printAndInLog_more('=========== 报错 ============')
        else:
            cy_log.printAndInLog_less('=========== 报错 ============')
            cy_log.printAndInLog_less('获取订单报错：' + str(e))
            cy_log.printAndInLog_less('订单id：' + newClientOrderId)
            cy_log.printAndInLog_less('=========== 报错 ============')

        return None
    else:
        pass

    return result

def cencel_orderwithId(items, isMore):
    
    result = None

    try:

        # 这里的限制是最大20 所以按照18个一组来做一下区分
        if len(items) > 18:
            if isMore:
                cy_log.printAndInLog_more('需要撤销的订单数量大于18 这里拆分一下')
            else:
                cy_log.printAndInLog_less('需要撤销的订单数量大于18 这里拆分一下')

            n_all_items = cy_operate.list_split(items, 18)

            for n_items in n_all_items:

                time.sleep(cy_config.min_sleep_amount)

                result = user_tradeAPI.cancel_multiple_orders(n_items)

        else:
            result = user_tradeAPI.cancel_multiple_orders(items)
        
        if isMore:
            cy_log.printAndInLog_more('订单撤销结果：' + str(result))
        else:
            cy_log.printAndInLog_less('订单撤销结果：' + str(result))

    except Exception as e:
        if isMore:
            cy_log.printAndInLog_more('=========== 报错 ============')
            cy_log.printAndInLog_more('撤销订单失败 ' + str(e))
            cy_log.printAndInLog_more('=========== 报错 ============')
        else:
            cy_log.printAndInLog_less('=========== 报错 ============')
            cy_log.printAndInLog_less('撤销订单失败 ' + str(e))
            cy_log.printAndInLog_less('=========== 报错 ============')
    else:
        pass
    
    return result

def cencel_orderwithCustomerId(symbol, order_id, isMore):
    
    symbol = symbol

    if 'SWAP' in symbol and '-' in symbol:
        pass
    else:
        symbol = symbol + '-SWAP'
        symbol = symbol.replace('USDT', '-USDT')

    result = None

    try:

        result = user_tradeAPI.cancel_order(symbol, clOrdId=order_id)

        if isMore:
            cy_log.printAndInLog_more('撤销订单 ' + str(result))
        else:
            cy_log.printAndInLog_less('撤销订单 ' + str(result))

    except Exception as e:
        if isMore:
            cy_log.printAndInLog_more('=========== 报错 ============')
            cy_log.printAndInLog_more('撤销订单失败 ' + str(e))
            cy_log.printAndInLog_more('=========== 报错 ============')
        else:
            cy_log.printAndInLog_less('=========== 报错 ============')
            cy_log.printAndInLog_less('撤销订单失败 ' + str(e))
            cy_log.printAndInLog_less('=========== 报错 ============')

        result = None
    else:
        pass
    
    return result

# 开多
def buy_order(symbol, price, quantity, newClientOrderId):

    if 'SWAP' in symbol and '-' in symbol:
        pass
    else:
        symbol = symbol + '-SWAP'
        symbol = symbol.replace('USDT', '-USDT')

    instId = symbol
    tdMode = 'cross'
    side = 'buy'
    posSide = 'long'
    ordType = 'limit'
    sz = quantity
    px = price
    clOrdId = newClientOrderId

    cy_log.printAndInLog_more('价格：' + str(price) + ' 张数：' + str(sz))

    result = None

    clOrdId = clOrdId.replace('-', '')
    clOrdId = clOrdId.replace('-', '')
    clOrdId = clOrdId.replace('-', '')

    try:
        result = user_tradeAPI.place_order(instId=instId, tdMode=tdMode, side=side, posSide=posSide, ordType=ordType, sz=sz, px=px, clOrdId=clOrdId, tag=cy_config.broker_code)
        cy_log.printAndInLog_more('开多结果：' + str(result))
    except Exception as e:
        cy_log.printAndInLog_more('=========== 报错 ============')
        cy_log.printAndInLog_more('buy 下单操作失败 ' + str(e))
        cy_log.printAndInLog_more('=========== 报错 ============')
    else:
        cy_log.printAndInLog_more('buy 下单成功')

    return result

# 平多
def sell_order(order, newClientOrderId, more_sell_increase):

    symbol = order['instId']
    price = order['fillPx']

    price = float(price) + float(price) * (float(more_sell_increase) / 100)
    price = round(price, cy_config.buy_price_point)

    quantity = order['fillSz']

    instId = symbol
    tdMode = 'cross'
    clOrdId = newClientOrderId
    side = 'sell'
    posSide = 'long'
    ordType = 'limit'
    sz = quantity
    px = price

    result = None

    clOrdId = clOrdId.replace('-', '')
    clOrdId = clOrdId.replace('-', '')
    clOrdId = clOrdId.replace('-', '')

    try:
        result = user_tradeAPI.place_order(instId=instId, tdMode=tdMode, side=side, clOrdId=clOrdId, posSide=posSide, ordType=ordType, sz=sz, px=px, tag=cy_config.broker_code)
        cy_log.printAndInLog_more('平多结果：' + str(result))
    except Exception as e:
        cy_log.printAndInLog_more('=========== 报错 ============')
        cy_log.printAndInLog_more('sell 下单操作失败 ' + str(e))
        cy_log.printAndInLog_more('=========== 报错 ============')
    else:
        cy_log.printAndInLog_more('sell 下单成功')
    
    return result

# 开空
def buy_order_open_less(symbol, price, quantity, newClientOrderId):

    if 'SWAP' in symbol and '-' in symbol:
        pass
    else:
        symbol = symbol + '-SWAP'
        symbol = symbol.replace('USDT', '-USDT')

    instId = symbol
    tdMode = 'cross'
    side = 'sell'
    posSide = 'short'
    ordType = 'limit'
    sz = quantity
    px = price
    clOrdId = newClientOrderId

    cy_log.printAndInLog_less('价格：' + str(price) + ' 张数：' + str(sz))
    
    clOrdId = clOrdId.replace('-', '')
    clOrdId = clOrdId.replace('-', '')
    clOrdId = clOrdId.replace('-', '')

    result = None

    try:
        result = user_tradeAPI.place_order(instId=instId, tdMode=tdMode, side=side, posSide=posSide, ordType=ordType, sz=sz, px=px, clOrdId=clOrdId, tag=cy_config.broker_code)
        cy_log.printAndInLog_less('开空结果：' + str(result))
    except Exception as e:
        cy_log.printAndInLog_less('=========== 报错 ============')
        cy_log.printAndInLog_less('buy 下单操作失败 ' + str(e))
        cy_log.printAndInLog_less('=========== 报错 ============')
    else:
        cy_log.printAndInLog_less('buy 下单成功')

    return result

# 平空
def sell_order_open_less(order, newClientOrderId, less_sell_increase):

    symbol = order['instId']
    price = order['fillPx']

    price = float(price) + float(price) * (float(less_sell_increase) / 100)
    price = round(price, cy_config.buy_price_point)

    quantity = order['fillSz']

    instId = symbol
    tdMode = 'cross'
    clOrdId = newClientOrderId
    side = 'buy'
    posSide = 'short'
    ordType = 'limit'
    sz = quantity
    px = price

    clOrdId = clOrdId.replace('-', '')
    clOrdId = clOrdId.replace('-', '')
    clOrdId = clOrdId.replace('-', '')

    result = None

    try:
        result = user_tradeAPI.place_order(instId=instId, tdMode=tdMode, side=side, clOrdId=clOrdId, posSide=posSide, ordType=ordType, sz=sz, px=px, tag=cy_config.broker_code)
        cy_log.printAndInLog_less('平空结果：' + str(result))
    except Exception as e:
        cy_log.printAndInLog_less('=========== 报错 ============')
        cy_log.printAndInLog_less('sell 下单操作失败 ' + str(e))
        cy_log.printAndInLog_less('=========== 报错 ============')
    else:
        cy_log.printAndInLog_less('sell 下单成功')
    
    return result

# 平多 平持仓 市价全平
def sell_order_more_risk(symbol):

    if 'SWAP' in symbol and '-' in symbol:
        pass
    else:
        symbol = symbol + '-SWAP'
        symbol = symbol.replace('USDT', '-USDT')

    result = None

    try:
        result = user_tradeAPI.close_positions(symbol, 'cross', 'long', '', tag = cy_config.broker_code)
        cy_log.printAndInLog_more('多持仓全平：' + str(result) + str(symbol))
    except Exception as e:
        cy_log.printAndInLog_more('=========== 报错 ============')
        cy_log.printAndInLog_more('多市价平仓 失败 ' + str(e))
        cy_log.printAndInLog_more('=========== 报错 ============')
    else:
        cy_log.printAndInLog_more('多持仓全平：' + str(result) + str(symbol))

    return result

# 平空 平持仓
def sell_order_less_risk(symbol):

    if 'SWAP' in symbol and '-' in symbol:
        pass
    else:
        symbol = symbol + '-SWAP'
        symbol = symbol.replace('USDT', '-USDT')

    result = None

    try:
        result = user_tradeAPI.close_positions(symbol, 'cross', 'short', '', tag = cy_config.broker_code)
        cy_log.printAndInLog_less('空持仓全平：' + str(result) + str(symbol))
    except Exception as e:
        cy_log.printAndInLog_less('=========== 报错 ============')
        cy_log.printAndInLog_less('空市价平仓 失败 ' + str(e))
        cy_log.printAndInLog_less('=========== 报错 ============')
    else:
        pass

    return result

def getklines(symbol, startTime, endTime):

    try:

        if 'SWAP' in symbol and '-' in symbol:
            pass
        else:
            symbol = symbol + '-SWAP'
            symbol = symbol.replace('USDT', '-USDT')

        result = None

        isLoopGO = True

        while isLoopGO:
            
            time.sleep(cy_config.sleep_amount)

            try:

                result = marketAPI.get_candlesticks(symbol, bar='4H', limit=300)
                reslut_code = result['code']

                if int(reslut_code) == 0:
                    result = result['data']
                    isLoopGO = False
                else:
                    cy_log.printAndInLog_k("获取k线失败：" + str(result))
                    isLoopGO = True

            except Exception as e:
                cy_log.printAndInLog_k("获取k线失败：" + str(e))
                isLoopGO = True
            else:
                isLoopGO = False

    except Exception as e:
        cy_log.printAndInLog_k("获取k线失败：" + str(e))
        result = None
    else:
        pass

    return result